const {
    ccclass,
    property
} = cc._decorator;

@ccclass
export default class ListView extends cc.Component {
    @property(cc.ScrollView)
    scroll: cc.ScrollView = null;
    @property(cc.Node)
    content: cc.Node = null;
    @property(cc.Node)
    item: cc.Node = null;
    @property
    itemScript: string = '';

    private _node_pool: cc.NodePool = null;
    private _base_content_y: number = 0;
    private _item_height: number = 0;
    private _list: any = null;
    private _list_index: number = 0;
    private _item_count: number = 0;
    private _last_content_y: number = 0;

    onLoad() {
        this.dataInit();
        this.scrollInit();
    }
    onEnable() {
        this.scroll.node.on('scrolling', this.scrolling, this);
        this.scroll.node.on('scroll-to-top', this.scrolling, this);
        this.scroll.node.on('scroll-to-bottom', this.scrolling, this);
        this.scroll.scrollToTop(0);
    }
    onDisable() {
        this.scroll.node.off('scrolling', this.scrolling, this);
        this.scroll.node.off('scroll-to-top', this.scrolling, this);
        this.scroll.node.off('scroll-to-bottom', this.scrolling, this);
    }
    onDestroy() {
        while (this.content.childrenCount) {
            this._node_pool.put(this.content.children[0]);
        }
        this._node_pool.clear();
    }
    dataInit() {
        // this._list = [];

        const data = [];
        for (let i = 0; i < 100; ++i) {
            data.push(i)
        }
        this._list = data;
        this._item_height = this.item.height;
        const viewHeight = this.content.parent.height;
        this._base_content_y = viewHeight - viewHeight * this.content.parent.anchorY;
        this._last_content_y = this._base_content_y;
        this.content.y = this._base_content_y;
        // this.content.height = 0;
        this._node_pool = new cc.NodePool();
        this._node_pool.put(this.item);
        this.dataListInit(this._list)
    }
    getNodePool() {
        return this._node_pool;
    }
    _addNextItem(data) {
        let y = 0;
        if (this.content.childrenCount) {
            y = this.content.children[this.content.childrenCount - 1].y - this._item_height;
        }
        let node = this._getItem();
        if (!node) return;
        node.parent = this.content;
        node.y = y;
        node.getComponent(this.itemScript).initData(data);
    }
    _addLastItem(data) {
        let y = this.content.children[0].y + this._item_height;
        let node = this._getItem();
        if (!node) return;
        node.y = y;
        this.content.insertChild(node, 0);
        node.getComponent(this.itemScript).initData(data);
    }
    _getItem() {
        if (!this._node_pool) return;
        let node = null;
        if (this._node_pool.size() > 0) {
            node = this._node_pool.get();
        } else {
            node = cc.instantiate(this.item);
        }
        return node;
    }
    moveItem(dir, data) {
        if (dir == 'up') {
            let temp_node = this.content.children[this.content.childrenCount - 1];
            this._node_pool.put(temp_node);
            this._addLastItem(data);
        } else if (dir == 'down') {
            let temp_node = this.content.children[0];
            this._node_pool.put(temp_node);
            this._addNextItem(data);
        }
    }
    disposeMin(offset_y) {
        let top_index = (offset_y - this._base_content_y) / this._item_height;
        top_index < 0 ? top_index = top_index - 1 : top_index = top_index;
        if (top_index < this._list_index && this._list_index > 0) {
            for (this._list_index; this._list_index >= top_index && this._list_index > 0; this._list_index -= 1) {
                this.moveItem('up', this._list[this._list_index - 1])
            }
        }

    }
    disposeMax(offset_y) {
        let top_index = (offset_y - this._base_content_y) / this._item_height;
        let bottom_index = top_index + this._item_count;
        let now_index = this._list_index + this._item_count;
        if (bottom_index >= now_index && this._list_index + this._item_count < this._list.length) {
            if (bottom_index >= this._list.length - 1) bottom_index = this._list.length;
            for (now_index; now_index < bottom_index; now_index++) {
                this._list_index += 1;
                this.moveItem('down', this._list[now_index]);
            }

        }

    }
    dataListInit(list) {
        this.setDataList(list);
    }
    setDataList(list) {
        this._list = list;
        this.content.height = this._item_height * this._list.length;
    }
    getDataList() {
        return this._list;
    }
    scrollInit() {
        this._list_index = 0;
        this._item_count = 0;
        for (let i = 0; i < this._list.length; i++) {
            this._item_count++;
            this._addNextItem(this._list[i]);
            if (this.scroll.node.height <= (this._item_count - 1) * this._item_height) {
                return;
            }
        }
    }
    scrolling(event) {
        let content_y = this.scroll.getContentPosition().y;

        if (content_y > this._last_content_y || content_y > this.content.height - this._base_content_y) {
            this.disposeMax(content_y - this._item_height)
        } else if (content_y < this._last_content_y || content_y < this._base_content_y) {
            this.disposeMin(content_y);
        }

        this._last_content_y = content_y;
    }
}